package com.newsnetwork.user.controller;

import com.newsnetwork.api.BaseController;
import com.newsnetwork.api.controller.user.PassportControllerApi;
import com.newsnetwork.enums.UserStatus;
import com.newsnetwork.grace.result.CommonJSONResult;
import com.newsnetwork.grace.result.ResponseStatusEnum;
import com.newsnetwork.pojo.AppUser;
import com.newsnetwork.pojo.bo.RegistLoginBO;
import com.newsnetwork.user.service.UserService;
import com.newsnetwork.utils.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * @author DingNing, HuangDekai
 * @date 2022/11/3 21:04
 * @Description:
 */
@RestController
public class PassportController extends BaseController implements PassportControllerApi {
    private static final Logger log = LoggerFactory.getLogger(PassportController.class);

    @Autowired
    private SMSUtils smsUtils;

    @Autowired
    private UserService userService;

    @Override
    public CommonJSONResult getSMSCode(String mobile, HttpServletRequest request) {
        // 获取用户 IP
        String userIp = IPUtil.getRequestIp(request);

        // 根据用户的ip进行限制, 限制用户在 60秒内只能获取一次验证码
        redisOperator.setnx60s(MOBILE_SMSCODE + ":" + userIp, userIp);

        // 生成随机验证码并发送短信
        String randomCode = RandomUtil.getFourBitRandom();
//        smsUtils.sendSMS(mobile, randomCode);

        // 把验证码存入 redis, 用于后续验证, 过期时间 30 * 60s
        redisOperator.set(MOBILE_SMSCODE + ":" + mobile, randomCode, 30 * 60);
        return CommonJSONResult.ok();
    }

    @Override
    public CommonJSONResult doLogin(@Valid RegistLoginBO registLoginBO,
                                    HttpServletRequest request,
                                    HttpServletResponse response) {
        // 判断 result 是否保存了错误的验证信息
//        if (result.hasErrors()) {
//            Map<String, String> errors = getErrors(result);
//            return CommonJSONResult.errorMap(errors);
//        }

        String mobile = registLoginBO.getMobile();
        String smsCode = registLoginBO.getSmsCode();

        // 校验验证码是否匹配
        String redisSMSCode = redisOperator.get(MOBILE_SMSCODE + ":" + mobile);
        if (StringUtils.isBlank(redisSMSCode) || !redisSMSCode.equalsIgnoreCase(smsCode)) {
            return CommonJSONResult.errorCustom(ResponseStatusEnum.SMS_CODE_ERROR);
        }

        // 查询数据库, 判断用户是否注册
        AppUser user = userService.queryMobileIsExist(mobile);
        // 用户不为空且已冻结
        if (user != null && user.getActiveStatus().equals(UserStatus.FROZEN.type)) {
            return CommonJSONResult.errorCustom(ResponseStatusEnum.USER_FROZEN);
        }
        // 用户为空则创建用户
        else if (user == null) {
            user = userService.createUser(mobile);
        }

        // 保存用户分布式会话的相关操作
        Integer userActiveStatus = user.getActiveStatus();
        if (!userActiveStatus.equals(UserStatus.FROZEN.type)) {
            // 保存 token 到 redis
            String uToken = UUID.randomUUID().toString();
            redisOperator.set(REDIS_USER_TOKEN + ":" + user.getId(), uToken);
            redisOperator.set(REDIS_USER_INFO + ":" + user.getId(), JsonUtils.objectToJson(user));

            // 保存用户 id 和 token 到 cookie 中
            setCookie(request, response, "utoken", uToken, COOKIE_MONTH);
            setCookie(request, response, "uid", user.getId(), COOKIE_MONTH);
        }

        // 用户登录或注册成功以后, 需要删除 redis 中的短信验证码, 验证码只能使用一次, 用过后则作废
        redisOperator.del(MOBILE_SMSCODE + ":" + mobile);

        // 返回用户状态
        return CommonJSONResult.ok(userActiveStatus);
    }

    /**
     * 用户退出 - 删除 redis 中的 utoken, cookie 中的 utoken 和 uid
     * @param userId 用户 id
     * @param request 请求
     * @param response 响应
     * @return CommonJSONResult.OK()
     */
    @Override
    public CommonJSONResult logout(String userId, HttpServletRequest request, HttpServletResponse response) {

        redisOperator.del(REDIS_USER_TOKEN + ":" + userId);
        setCookie(request, response, "utoken", "",COOKIE_DELETED);
        setCookie(request, response, "uid", "",COOKIE_DELETED);

        return CommonJSONResult.ok();
    }
}
